#include "ndef.h"
#include <string.h>
#include "nfcForum.h"
#include "rtdTypes.h"
#include "NT3H.h"

// 定义函数指针数组，用于组合RTD记录
typedef uint8_t (*composeRtdPtr)(const NDEFDataStr *ndef, NDEFRecordStr *ndefRecord, uint8_t *I2CMsg);
static composeRtdPtr composeRtd[] = {composeRtdText, composeRtdUri};

// 处理第一个记录
int16_t firstRecord(UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition) {
    (void)page; // 显式标记为未使用
    (void)rtdPosition; // 显式标记为未使用
    NDEFRecordStr record;
    NDEFHeaderStr header;
    uint8_t typeFunct = 0;

    switch (data->rtdType) {
    case RTD_TEXT:
        typeFunct = 0;
        break;
    case RTD_URI:
        typeFunct = 1;
        break;
    default:
        return -1;
    }

    // 清空所有缓冲区
    memset(&record, 0, sizeof(NDEFRecordStr));
    memset(nfcPageBuffer, 0, NFC_PAGE_SIZE);

    // 这是第一个记录
    header.startByte = NDEF_START_BYTE;
    composeNDEFMBME(true, true, &record);

    // 准备NDEF头部和有效载荷
    uint8_t recordLength = composeRtd[typeFunct](data, &record, &nfcPageBuffer[sizeof(NDEFHeaderStr)]);
    header.payloadLength = data->rtdPayloadlength + recordLength;

    // 写入第一个记录
    memcpy(nfcPageBuffer, &header, sizeof(NDEFHeaderStr));

    return sizeof(NDEFHeaderStr) + recordLength;
}

// 添加记录
int16_t addRecord(UncompletePageStr *pageToUse, const NDEFDataStr *data, RecordPosEnu rtdPosition) {
    NDEFRecordStr record;
    NDEFHeaderStr header = {0};
    uint8_t newRecordPtr, mbMe;
    uint8_t tmpBuffer[NFC_PAGE_SIZE];
    uint8_t typeFunct = 0;

    switch (data->rtdType) {
    case RTD_TEXT:
        typeFunct = 0;
        break;
    case RTD_URI:
        typeFunct = 1;
        break;
    default:
        return -1;
    }

    // 首先更改第一个记录的头部
    NT3HReadHeaderNfc(&newRecordPtr, &mbMe);
    record.header = mbMe;
    composeNDEFMBME(true, false, &record); // 这是第一个记录
    mbMe = record.header;

    memset(&record, 0, sizeof(NDEFRecordStr));
    memset(tmpBuffer, 0, NFC_PAGE_SIZE);

    // 准备第二个记录
    uint8_t recordLength = composeRtd[typeFunct](data, &record, tmpBuffer);

    if (rtdPosition == NDEFMiddlePos) {
        // 这是中间的记录，调整缓冲区
        composeNDEFMBME(false, false, &record);
    } else if (rtdPosition == NDEFLastPos) {
        // 这是最后的记录，调整缓冲区
        composeNDEFMBME(false, true, &record);
    }

    tmpBuffer[0] = record.header;
    header.payloadLength += data->rtdPayloadlength + recordLength;

    // 保存第一页的新长度值
    NT3HWriteHeaderNfc((newRecordPtr + header.payloadLength), mbMe);

    // 使用最后一个有效页面并开始添加新记录
    NT3HReadUserData(pageToUse->page);
    if (pageToUse->usedBytes + recordLength < NFC_PAGE_SIZE) {
        memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, recordLength);
        return recordLength + pageToUse->usedBytes;
    } else {
        uint8_t byteToCopy = NFC_PAGE_SIZE - pageToUse->usedBytes;
        memcpy(&nfcPageBuffer[pageToUse->usedBytes], tmpBuffer, byteToCopy);
        NT3HWriteUserData(pageToUse->page, nfcPageBuffer);
        pageToUse->page++;
        pageToUse->usedBytes = recordLength - byteToCopy;
        memcpy(nfcPageBuffer, &tmpBuffer[byteToCopy], pageToUse->usedBytes);
        return pageToUse->usedBytes;
    }
}

// 写入用户有效载荷
static bool writeUserPayload(int16_t payloadPtr, const NDEFDataStr *data, UncompletePageStr *addPage) {
    uint8_t addedPayload;
    bool ret = false;
    bool endRecord = false;
    uint8_t copyByte = 0;

    if (NFC_PAGE_SIZE > payloadPtr) {
        if (data->rtdPayloadlength > NFC_PAGE_SIZE - payloadPtr)
            copyByte = NFC_PAGE_SIZE - payloadPtr;
        else
            copyByte = data->rtdPayloadlength;
    }

    memcpy(&nfcPageBuffer[payloadPtr], data->rtdPayload, copyByte);
    addedPayload = copyByte;

    if ((addedPayload >= data->rtdPayloadlength) && ((payloadPtr + copyByte) < NFC_PAGE_SIZE)) {
        nfcPageBuffer[(payloadPtr + copyByte)] = NDEF_END_BYTE;
        endRecord = true;
    }

    ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);

    while (!endRecord) {
        addPage->page++;
        memset(nfcPageBuffer, 0, NFC_PAGE_SIZE);

        if (addedPayload == data->rtdPayloadlength) {
            nfcPageBuffer[0] = NDEF_END_BYTE;
            ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);
            endRecord = true;
            if (ret == false) {
                errNo = NT3HERROR_WRITE_NDEF_TEXT;
            }
            goto end;
        }

        if (addedPayload < data->rtdPayloadlength) {
            if ((data->rtdPayloadlength - addedPayload) < NFC_PAGE_SIZE) {
                memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], (data->rtdPayloadlength - addedPayload));
                nfcPageBuffer[(data->rtdPayloadlength - addedPayload)] = NDEF_END_BYTE;
            } else {
                memcpy(nfcPageBuffer, &data->rtdPayload[addedPayload], NFC_PAGE_SIZE);
            }

            addedPayload += NFC_PAGE_SIZE;
            ret = NT3HWriteUserData(addPage->page, nfcPageBuffer);

            if (ret == false) {
                errNo = NT3HERROR_WRITE_NDEF_TEXT;
                goto end;
            }
        } else {
            endRecord = true;
        }
    }

end:
    return ret;
}

// 定义函数指针数组，用于添加记录
typedef int16_t (*addFunct_T)(UncompletePageStr *page, const NDEFDataStr *data, RecordPosEnu rtdPosition);
static addFunct_T addFunct[] = {firstRecord, addRecord, addRecord};

// 写入NDEF记录
bool NT3HwriteRecord(const NDEFDataStr *data) {
    uint8_t recordLength = 0, mbMe;
    UncompletePageStr addPage;
    addPage.page = 0;

    if (data->ndefPosition != NDEFFirstPos) {
        NT3HReadHeaderNfc(&recordLength, &mbMe);
        addPage.page = (recordLength + sizeof(NDEFHeaderStr) + 1) / NFC_PAGE_SIZE;
        addPage.usedBytes = (recordLength + sizeof(NDEFHeaderStr) + 1) % NFC_PAGE_SIZE - 1;
    }

    int16_t payloadPtr = addFunct[data->ndefPosition](&addPage, data, data->ndefPosition);
    if (payloadPtr == -1) {
        errNo = NT3HERROR_TYPE_NOT_SUPPORTED;
        return false;
    }

    return writeUserPayload(payloadPtr, data, &addPage);
}

